#include <iostream>
#include <queue>
#include <cstdlib>
#include <unistd.h>
#include <pthread.h>
using namespace std;
const uint32_t defaultcap=15;
template <class T>
class Blockqueue{
public:
    Blockqueue(uint32_t cap=defaultcap):cap_(cap)
    {
        pthread_cond_init(&concond_,nullptr);
        pthread_cond_init(&procond_,nullptr);
        pthread_mutex_init(&mutex_head,nullptr);
        pthread_mutex_init(&mutex_tail,nullptr);
    }
    ~Blockqueue(){
        pthread_cond_destroy(&concond_);
        pthread_cond_destroy(&procond_);
        pthread_mutex_destroy(&mutex_head);
        pthread_mutex_destroy(&mutex_tail);
    }
    void push(const T &in){//生产
        //加锁
        //判断队列是否满
        //队列满了，不生产，等待唤醒
        //队列不满，生产
        //解锁
        lockqueue(&mutex_tail);
        while(isfull()){    //如果满了，等待被唤醒生产
            prowaitblock();
        }
        pushCore(in);
        unlockqueue(&mutex_tail);
        //唤醒消费者
        wakecon();
    }
    T pop(){//消费
    	//加锁
        //判断是否为空
        //不消费，等待唤醒
        //消费
        //解锁
        lockqueue(&mutex_head);
        while(isempty()){
        	conwaitblock();
        }
        T tmp=popcore();
        unlockqueue(&mutex_head);
        wakepro();
        return tmp;
    }
private:
    void prowaitblock(){
        pthread_cond_wait(&procond_,&mutex_tail);
    }
    void conwaitblock(){
        pthread_cond_wait(&concond_,&mutex_head);
    }
    void wakecon(){
        pthread_cond_signal(&concond_);
    }
    void wakepro(){
        pthread_cond_signal(&procond_);
    }
    void lockqueue(pthread_mutex_t* mutexq){
        pthread_mutex_unlock(mutexq);
    }
    void unlockqueue(pthread_mutex_t* mutexq){
        pthread_mutex_unlock(mutexq);
    }
    bool isfull(){
        return bq_.size()==cap_;
    }
    bool isempty(){
        return bq_.empty();
    }
    void pushCore(const T &in){
        bq_.push(in);
    }
    T popcore(){
        T tmp=bq_.front();
        bq_.pop();
        return tmp;
    }
private:
    queue<T> bq_;	//阻塞队列
    uint32_t cap_;	//容量
    pthread_mutex_t mutex_head;	//保护阻塞队列头部的互斥量
    pthread_mutex_t mutex_tail;
    pthread_cond_t concond_;	//让消费者等待的条件变量
    pthread_cond_t procond_;	//让生产者等待的条件
};
